
package nsga;

import java.io.BufferedReader;
import java.io.FileReader;
import java.util.StringTokenizer;

public class QAP implements Problema
{
    private double[][] distancias;
    private double[][] flujo1;
    private double[][] flujo2;
    private int length;
    private int cantidadDigitos;
    
    public QAP(double[][] flujo1,double[][] flujo2, double[][] distancias)
    {
        this.flujo1=flujo1;
        this.flujo2=flujo2;
        this.distancias=distancias;
        length=distancias.length;
        cantidadDigitos=(int)Math.pow(10, String.valueOf(length).length());
    }

    public int getTipo()
    {
        return 1;
    }
    
    public int getLength()
    {
        return length;
    }
    
    public void setFitness(Individuo individuo)
    {
        double[] result=new double[2];
        int[] localidades=((IndividuoQAP)individuo).getLocalidades();
        for(int i=0;i<(length-1);i++)
        {
            for(int j=i+1;j<length;j++)
            {
                result[0]+=distancias[i][j]*flujo1[localidades[i]][localidades[j]];
                result[1]+=distancias[i][j]*flujo2[localidades[i]][localidades[j]];
            }
        }
        individuo.setFitness(result);
    }
    
    public Individuo[] cruzar(Individuo individuo1, Individuo individuo2)
    {
        IndividuoQAP[] result=new IndividuoQAP[2];
        result[0]=new IndividuoQAP(length);
        result[1]=new IndividuoQAP(length);
        int[] localidades1=((IndividuoQAP)individuo1).getLocalidades();
        int[] localidades2=((IndividuoQAP)individuo2).getLocalidades();
        boolean turno=false;
        for(int i=0;i<length;i++)
        {
            if(!turno)
            {
                if(!result[0].setEdificioToLocalidad(localidades1[i], i))
                {
                    if(!result[0].setEdificioToLocalidad(localidades2[i], i))
                    {
                        do
                        {
                            int rand;
                            do
                            {
                                rand=(int)(Math.random()*cantidadDigitos);
                            }
                            while((rand>=length)||(localidades1[i]==rand)||(localidades2[i]==rand));
                            if(result[0].setEdificioToLocalidad(rand, i))
                            {
                                break;
                            }
                        }
                        while(true);
                    }
                }
                if(!result[1].setEdificioToLocalidad(localidades2[i], i))
                {
                    if(!result[1].setEdificioToLocalidad(localidades1[i], i))
                    {
                        do
                        {
                            int rand;
                            do
                            {
                                rand=(int)(Math.random()*cantidadDigitos);
                            }
                            while((rand>=length)||(localidades2[i]==rand)||(localidades1[i]==rand));
                            if(result[1].setEdificioToLocalidad(rand, i))
                            {
                                break;
                            }
                        }
                        while(true);
                    }
                }
            }
            else
            {
                if(!result[0].setEdificioToLocalidad(localidades2[i], i))
                {
                    if(!result[0].setEdificioToLocalidad(localidades1[i], i))
                    {
                        do
                        {
                            int rand;
                            do
                            {
                                rand=(int)(Math.random()*cantidadDigitos);
                            }
                            while((rand>=length)||(localidades2[i]==rand)||(localidades1[i]==rand));
                            if(result[0].setEdificioToLocalidad(rand, i))
                            {
                                break;
                            }
                        }
                        while(true);
                    }
                }
                if(!result[1].setEdificioToLocalidad(localidades1[i], i))
                {
                    if(!result[1].setEdificioToLocalidad(localidades2[i], i))
                    {
                        do
                        {
                            int rand;
                            do
                            {
                                rand=(int)(Math.random()*cantidadDigitos);
                            }
                            while((rand>=length)||(localidades1[i]==rand)||(localidades2[i]==rand));
                            if(result[1].setEdificioToLocalidad(rand, i))
                            {
                                break;
                            }
                        }
                        while(true);
                    }
                }
            }
            turno=!turno;
        }
        return result;
    }
    
    public static QAP main(String args)throws Exception
    {
        BufferedReader bufferedReader=new BufferedReader(new FileReader(args));
        int length=Integer.parseInt(bufferedReader.readLine());
        double[][] flujo1=new double[length][length];
        for(int i=0;i<length;i++)
        {
            StringTokenizer stringTokenizer=new StringTokenizer(bufferedReader.readLine());
            int j=0;
            while(stringTokenizer.hasMoreTokens())
            {
                flujo1[i][j]=Double.parseDouble(stringTokenizer.nextToken());
                j++;
            }
        }
        bufferedReader.readLine();
        double[][] flujo2=new double[length][length];
        for(int i=0;i<length;i++)
        {
            StringTokenizer stringTokenizer=new StringTokenizer(bufferedReader.readLine());
            int j=0;
            while(stringTokenizer.hasMoreTokens())
            {
                flujo2[i][j]=Double.parseDouble(stringTokenizer.nextToken());
                j++;
            }
        }
        bufferedReader.readLine();
        double[][] distancias=new double[length][length];
        for(int i=0;i<length;i++)
        {
            StringTokenizer stringTokenizer=new StringTokenizer(bufferedReader.readLine());
            int j=0;
            while(stringTokenizer.hasMoreTokens())
            {
                distancias[i][j]=Double.parseDouble(stringTokenizer.nextToken());
                j++;
            }
        }
        return new QAP(flujo1, flujo2, distancias);
    }
    
}
